/*******************************************************************
 * (c) Copyrignt 2023 广州万协通信息技术有限公司
 * All right reserved
 *
 * 文件名称：	iot_se_vendor.h
 * 摘要：		安全模块应用接口
 *
 * 取代版本：	V1.0
 * 原作者：		wangqiang@wisectech.com.cn
 * 日期：		2023.12.01
 ********************************************************************/
#ifndef _PAL_IOT_SE_LIB__
#define _PAL_IOT_SE_LIB__

///////可见宏声明////////////
#ifdef _WIN32

#ifdef PAL_DLL_BUILD
#define PAL_API _declspec(dllexport)
#elif defined PAL_DLL_USE
#define PAL_API _declspec(dllimport)
#else
#define PAL_API
#endif

// GCC Specific
#elif defined __GNUC__
#if __GNUC__ >= 4
#define PAL_API __attribute__((visibility("default")))
#else
#define PAL_API
#endif /// end __GNUC__

// Others
#else
#define PAL_API
#endif
///////可见宏声明////////////

//////基础类型定义///////////
#ifndef __WXT_TYPES_H__
#define __WXT_TYPES_H__
typedef signed char int8;
typedef unsigned char uint8;
typedef signed short int16;
typedef unsigned short uint16;
typedef signed int int32;
typedef unsigned int uint32;
#endif //__WXT_TYPES_H__
//////基础类型定义///////////

#define DATA_ENCODE_BASE64 0
#define DATA_ENCODE_BIN 1

typedef enum
{
	CERT_TYPE_ENCRYPT,
	CERT_TYPE_SIGN,
	CERT_TYPE_CA,
} CertType;

#ifdef __cplusplus
extern "C"
{
#endif // __cplusplus

	typedef struct Struct_SEAPPINFO
	{
		unsigned char Version;		// 版本号,设置为1.0
		unsigned char StartTime[4]; // 启用时间格式：YYYYMMDD
		unsigned char Algorithm;	// 支持算法类型 0 ：SM2 算法
		unsigned char DeviceType;	// 设备类型 0：网关，1：终端
		unsigned char SEID[16];		// SEID （SE序列号）
		unsigned char ActiveStatus; // 激活状态(查询时有效),高 4 位：0000：未启用   1111： 已启用  其它：预留
									// 低 4 位：0000：预留
		unsigned char Reserved[40]; // 保留扩展
	} SEAPPINFO, *PSEAPPINFO;

	/// 环境/设备管理

	/// 对设备环境进行初始化，可指定SE相关参数，包括：应用名称，容器名称和用户口令
	///	\param [out] phEnvHandle: 输出环境句柄
	///	\param [in] index: 指定SE索引，默认为0，即系统上第一个SE
	///	\param [in] pszDeviceId: 指定终端设备ID，如IMEI
	///	\param [in] pszApplicationName: 指定应用名称，当传入NULL时，采用默认应用名
	///	\param [in] pszContainerName: 指定容器名称，当传入NULL时，采用默认应用名
	///	\param [in] pszPin: 指定用户口令，当传入NULL时，采用默认PIN
	/// \return 0:成功, 其它:失败
	unsigned int PAL_API SE_Initialize(void **phEnvHandle, unsigned int index, char *pszDeviceId,
									   char *pszApplicationName, char *pszContainerName, char *pszPin);

	/// 对设备环境进行反初始化，释放相关资源
	///	\param [in] phEnvHandle: 环境句柄
	/// \return 0:成功, 其它:失败
	unsigned int PAL_API SE_EnvUninit(void *hEnvHandle);

	/// 设置SE相关信息
	///	\param [in] phEnvHandle: 环境句柄
	///	\param [in] pSeAppInfo: SE应用信息结构体
	/// \return 0:成功, 其它:失败
	unsigned int PAL_API SE_SetSEInfo(void *hEnvHandle, SEAPPINFO *pSeAppInfo);

	/// 设置SE相关信息
	///	\param [in] phEnvHandle: 环境句柄
	///	\param [out] pSeAppInfo: SE应用信息结构体
	/// \return 0:成功, 其它:失败
	unsigned int PAL_API SE_GetSEInfo(void *hEnvHandle, SEAPPINFO *pSeAppInfo);

	/// 获取绑定到 SE 的设备 ID
	///	\param [in] phEnvHandle: 环境句柄
	///	\param [out] pucDevId: 设备ID
	///	\param [in/out] pnDevIdLen: 设备ID长度
	/// \return 0:成功, 其它:失败
	unsigned int PAL_API SE_GetBindedDeviceId(void *hEnvHandle, unsigned char *pucDevId, unsigned int *pnDevIdLen);

	/// 激活绑定到 SE 的设备 ID
	/// 激活后，设备在使用SE之前应调用SE_GetDeviceId获取设备ID，并与当前设备ID比对，确定设备ID一致后，才可继续使用
	/// 激活后，套件将不在支持SE_BindDeviceId接口
	///	\param [in] phEnvHandle: 环境句柄
	///	\param [in] pucDevId: 设备ID
	///	\param [in] nDevIdLen: 设备ID长度
	/// \return 0:成功, 其它:失败
	unsigned int PAL_API SE_ActiveDeviceId(void *hEnvHandle);

	/// 获取SEID
	///	\param [in] phEnvHandle: 环境句柄
	///	\param [out] pszSEID: 返回设备SEID，长度为16个字节
	/// \return 0:成功, 其它:失败
	unsigned int PAL_API SE_GetSEID(void *hEnvHandle, char *pszSEID);

	/// 更新固件
	///	\param [in] phEnvHandle: 环境句柄
	///	\param [in] pucFirmware: 固件数据
	///	\param [in] nFirmwareLen: 固件数据长度
	/// \return 0:成功, 其它:失败
	unsigned int PAL_API SE_UpdateFirmware(void *hEnvHandle, unsigned char *pucFirmware, unsigned int nFirmwareLen);

	/// 数据/证书/密钥管理

	/// 导出SE中保存的证书
	///	\param [in] phEnvHandle: 环境句柄
	///	\param [in] bSignFlag: 证书类型，0-签名证书，1-加密证书
	///	\param [out] pucCert: 证书内容
	///	\param [in/out] pnCertLen: 证书长度
	/// \return 0:成功, 其它:失败
	unsigned int PAL_API SE_ExportCertificate(void *hEnvHandle, unsigned char bSignFlag, unsigned char *pucCert, unsigned int *pnCertLen);

	/// 向SE导入证书
	///	\param [in] phEnvHandle: 环境句柄
	///	\param [in] bSignFlag: 证书类型，0-签名证书，1-加密证书
	///	\param [out] pucCert: 证书内容
	///	\param [in] nCertLen: 证书长度
	/// \return 0:成功, 其它:失败
	unsigned int PAL_API SE_ImportCertificate(void *hEnvHandle, unsigned char bSignFlag, unsigned char *pucCert, unsigned int nCertLen);


	/// 将服务端发行的对称密钥下载到SE，作为会话密钥保存
	///	\param [in] phEnvHandle: 环境句柄
	///	\param [in] nAlgId: 算法标识，SGD_SM4_ECB 或 SGD_SM4_CBC
	///	\param [in] pucWrapedData: 会话密钥密文，二进制格式，暂不支持base64格式
	///	\param [in] nWrapedLen: 会话密钥密文长度
	/// \return 0:成功, 其它:失败
	unsigned int PAL_API SE_ImportSessionKey(void *hEnvHandle, unsigned int nAlgId,unsigned char *pucWrapedData,unsigned int nWrapedLen);

	/// 生成证书请求，用于向服务端申请证书
	///	\param [in] phEnvHandle: 环境句柄
	///	\param [in] szCountry: 国家
	///	\param [in] szState: 省
	///	\param [in] szLocality: 市
	///	\param [in] szOrg: 组织机构
	///	\param [in] szOrg_unit: 单位部门 
	///	\param [in] szCommon_name: 通用名
	///	\param [out] pucP10Req: 证书请求，base64编码
	///	\param [in/out] pnP10ReqLen: 证书请求长度
	/// \return 0:成功, 其它:失败
	unsigned int PAL_API SE_GenP10ReqData(void *hEnvHandle, const char *szCountry, const char *szState, const char *szLocality,
											const char *szOrg, const char *szOrg_unit, const char *szCommon_name, unsigned char *pucP10Req, unsigned int *pnP10ReqLen);

	/// 获取证书序列号
	///	\param [in] phEnvHandle: 环境句柄
	///	\param [in] pucCert: 证书内容，二进制格式
	///	\param [in] nCertLen: 证书内容长度
	///	\param [out] pucSn: 证书序列号
	///	\param [in/out] pnSnLen: 证书序列号长度
	/// \return 0:成功, 其它:失败
	unsigned int PAL_API SE_GetCertSn(void *hEnvHandle, unsigned char *pucCert, unsigned int nCertLen, unsigned char *pucSn, unsigned int *pnSnLen);

	/// 生成认证数据
	///	\param [in] phEnvHandle: 环境句柄
	///	\param [in] pucData: 输入数据
	///	\param [in] nDataLen: 输入数据长度
	///	\param [out] pucSignedData: 输出认证数据
	///	\param [in/out] pnSignedDataLen: 输出认证数据长度
	/// \return 0:成功, 其它:失败
	unsigned int PAL_API SE_GenP7AuthData(void *hEnvHandle, unsigned char *pucData, unsigned int nDataLen, unsigned char *pucSignedData, unsigned int *pnSignedDataLen);

	/// 生成认证数据(信息箱部分)
	///	\param [in] phEnvHandle: 环境句柄
	///	\param [in] pucData: 输入数据
	///	\param [in] nDataLen: 输入数据长度
	///	\param [out] pucSignedData: 输出SM2签名
	///	\param [in/out] pnSignedDataLen: 输出签名长度
	///	\param [out] Cert: 输出证书
	///	\param [out] CertLen: 输出证书长度
	/// \return 0:成功, 其它:失败
	unsigned int PAL_API SE_GenP7_c(void *hEnvHandle, unsigned char *pucData, unsigned int nDataLen, unsigned char *pucSignedData, unsigned int *pnSignedDataLen, unsigned char* Cert, unsigned int* CertLen);
	
	/// 生成认证数据(服务端部分)
	///	\param [in/out] pucSignedData: 输入SM2签名输出认证数据
	///	\param [in/out] pnSignedDataLen: 输出认证数据长度
	///	\param [in] Cert: 输入证书
	///	\param [in] CertLen: 输入证书长度
	///	\param [in] pucData: 输入数据
	///	\param [in] nDataLen: 输入数据长度
	/// \return 0:成功, 其它:失败
	unsigned int PAL_API SE_GenP7_s(unsigned char *pucSignedData, unsigned int *pnSignedDataLen, unsigned char* Cert, unsigned int CertLen, unsigned char *pucData, unsigned int nDataLen);

	/// 对称算法运算(使用SE_ImportSessionKey接口导入的会话密钥)
	///	\param [in] phEnvHandle: 环境句柄
	///	\param [in] nOpType: 操作类型，0-加密，1-解密
	///	\param [in] pucIv: 初始值，ECB模式时无效
	///	\param [in] nIvLen: 初始值长度
	///	\param [in] pucIn: 输入数据
	///	\param [in] nInLen: 输入数据长度
	///	\param [in] pucOut: 输出结果
	///	\param [in/out] pnOutLen: 输出结果长度，输入时表示输出缓冲区长度
	/// \return 0:成功, 其它:失败
	unsigned int PAL_API SE_SymmOp(void *hEnvHandle, unsigned int nOpType,
									unsigned char *pucIv, unsigned int nIvLen,
									unsigned char *pucIn, unsigned int nInLen,
									unsigned char *pucOut, unsigned int *pnOutLen);
	/// 密码服务类

	/// 生成随机数
	///	\param [in] phEnvHandle: 环境句柄
	///	\param [in] pucRand: 随机数缓冲区
	///	\param [in] nRandLen: 随机数长度
	/// \return 0:成功, 其它:失败
	unsigned int PAL_API SE_GenRandom(void *hEnvHandle, unsigned char *pucRand, unsigned int nRandLen);

	/// 导出SE中保存的公钥
	///	\param [in] phEnvHandle: 环境句柄
	///	\param [in] bSignFlag: 公钥类型，0-签名公钥，1-加密公钥
	///	\param [out] pucPublicKey: 公钥内容
	///	\param [in/out] pnPublicKeyLen: 公钥长度
	/// \return 0:成功, 其它:失败
	unsigned int PAL_API SE_ExportPublicKey(void *hEnvHandle, unsigned char bSignFlag, unsigned char *pucPublicKey, unsigned int *pnPublicKeyLen);

	/// ECC私钥签名
	///	\param [in] phEnvHandle: 环境句柄
	///	\param [in] pucInData: 待签名数据
	///	\param [in] nInDataLen: 待签名数据长度（固定为32字节）
	///	\param [out] pucSignature: 签名结果
	///	\param [in/out] pnSignatureLen: 签名结果长度
	///	\param [in] nSignatureFormat: 签名结果格式，0-base64, 1-二进制
	/// \return 0:成功, 其它:失败
	unsigned int PAL_API SE_SignData_ECC(void *hEnvHandle, unsigned char *pucInData, unsigned int nInDataLen,
										 unsigned char *pucSignature, unsigned int *pnSignatureLen, unsigned int nSignatureFormat);

	/// ECC私钥解密
	///	\param [in] phEnvHandle: 环境句柄
	///	\param [in] pucInData: 待解密数据
	///	\param [in] nInDataLen: 待解密数据长度
	///	\param [out] pucOutData: 解密结果
	///	\param [in/out] pnOutDataLen: 解密结果长度
	///	\param [in] nResultFormat: 解密结果格式，0-base64, 1-二进制
	/// \return 0:成功, 其它:失败
	unsigned int PAL_API SE_DecryptData_ECC(void *hEnvHandle, unsigned char *pucInData, unsigned int nInDataLen,
											unsigned char *pucOutData, unsigned int *pnOutDataLen, unsigned int nResultFormat);

	/// 摘要运算
	///	\param [in] phEnvHandle: 环境句柄
	///	\param [in] pucData: 待计算数据
	///	\param [in] nDataLen: 待计算数据长度
	///	\param [out] pucHash: 摘要结果
	///	\param [in/out] pnHashLen: 摘要结果长度
	/// \return 0:成功, 其它:失败
	unsigned int PAL_API SE_Digest(void *hEnvHandle, unsigned char *pucData, unsigned int nDataLen,
								   unsigned char *pucHash, unsigned int *pnHashLen);

	/// 对称算法运算(使用数字信封)
	///	\param [in] phEnvHandle: 环境句柄
	///	\param [in] pucData: 待计算数据
	///	\param [in] nOpType: 操作类型，0-加密，1-解密
	///	\param [in] nAlgType: 算法标识
	///	\param [in] pucEnvelop: 数字信封
	///	\param [in] nEnvelopLen: 数字信封长度
	///	\param [in] pucIv: 初始值，ECB模式时无效
	///	\param [in] nIvLen: 初始值长度
	///	\param [in] pucIn: 输入数据
	///	\param [in] nInLen: 输入数据长度
	///	\param [out] pucOut: 输出结果
	///	\param [in/out] pnOutLen: 输出结果长度，输入时表示输出缓冲区长度
	/// \return 0:成功, 其它:失败
	unsigned int PAL_API SE_SymmOpEx(void *hEnvHandle, unsigned int nOpType, unsigned int nAlgType,
								   unsigned char *pucEnvelop, unsigned int nEnvelopLen,
								   unsigned char *pucIv, unsigned int nIvLen,
								   unsigned char *pucIn, unsigned int nInLen,
								   unsigned char *pucOut, unsigned int *pnOutLen);

	/// 证书校验
	///	\param [in] phEnvHandle: 环境句柄
	///	\param [in] pucData: 待计算数据
	///	\param [in] pucCaCert: CA证书
	///	\param [in] nCaCertLen: CA证书长度，当为0时，自动使用SE内存储的CA证书进行验证
	///	\param [in] pucUserCert: 用户证书
	///	\param [in] nUserCertLen: 用户证书长度
	/// \return 0:成功, 其它:失败
	unsigned int PAL_API SE_ValidateCert(void *hEnvHandle, unsigned char *pucCaCert, unsigned int nCaCertLen,
										 unsigned char *pucUserCert, unsigned int nUserCertLen);

	/// 基于证书的ECC公钥加密
	///	\param [in] phEnvHandle: 环境句柄
	///	\param [in] pucCert: DER编码证书
	///	\param [in] nCertLen: 证书长度
	///	\param [in] pucInData: 输入数据
	///	\param [in] nInDataLen: 输入数据长度
	///	\param [in] pucOutData: 输出数据
	///	\param [in/out] pnOutDataLen: 输出数据长度
	/// \return 0:成功, 其它:失败
	unsigned int PAL_API SE_PublicKeyEncByCert_ECC(void *hEnvHandle, unsigned char *pucCert, unsigned int nCertLen,
												   unsigned char *pucInData, unsigned int nInDataLen,
												   unsigned char *pucOutData, unsigned int *pnOutDataLen);

	/// 基于证书的ECC公钥验签
	///	\param [in] phEnvHandle: 环境句柄
	///	\param [in] pucCert: DER编码证书
	///	\param [in] nCertLen: 证书长度
	///	\param [in] pucInData: 待验证数据
	///	\param [in] nInDataLen: 待验证数据长度
	///	\param [in] pucSignData: 签名数据
	///	\param [in] nSignDataLen: 签名数据长度
	/// \return 0:成功, 其它:失败
	unsigned int PAL_API SE_PublicKeyVerifyByCert_ECC(void *hEnvHandle, unsigned char *pucCert, unsigned int nCertLen,
													  unsigned char *pucInData, unsigned int nInDataLen,
													  unsigned char *pucSignData, unsigned int nSignDataLen);

#ifdef __cplusplus
}
#endif

#endif // _PAL_IOT_SE_LIB__
